package com.regulareport.form.service.impl;

import com.regulareport.common.core.domain.entity.ReportPlanDetail;
import com.regulareport.common.core.domain.entity.ReportPlan;
import com.regulareport.common.core.domain.entity.ReportTask;
import com.regulareport.common.enums.*;
import com.regulareport.common.utils.RegularUtil;
import com.regulareport.common.utils.SecurityUtils;
import com.regulareport.form.domain.*;
import com.regulareport.form.mapper.ReportPlanDetailMapper;
import com.regulareport.form.mapper.ReportTaskMapper;
import com.regulareport.form.mapper.ReportPlanMapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Service
public class ReportPlanService {
    private final ReportPlanMapper reportPlanMapper;
    private final ReportTaskMapper reportTaskMapper;
    private final ReportPlanDetailMapper reportPlanDetailMapper;

    public ReportPlanService(ReportPlanMapper reportPlanMapper, ReportTaskMapper reportTaskMapper, ReportPlanDetailMapper reportPlanDetailMapper) {
        this.reportPlanMapper = reportPlanMapper;
        this.reportTaskMapper = reportTaskMapper;
        this.reportPlanDetailMapper = reportPlanDetailMapper;
    }

    @Transactional(rollbackFor = Throwable.class)
    public void addReportPlan(AddReportPlanReq reportPlanReq) throws Exception {
        if (reportPlanReq.getReportIds() == null || reportPlanReq.getReportIds().isEmpty()) {
            throw new Exception("报表不能为空");
        }

        if (reportPlanReq.getDeptIds() == null || reportPlanReq.getDeptIds().isEmpty()) {
            throw new Exception("机构不能为空");
        }

        ReportPlan reportPlan = new ReportPlan();
        reportPlan.setPlanName(reportPlanReq.getPlanName());
        int num = reportPlanMapper.countPlan(reportPlan);
        if (num > 0) {
            throw new Exception("计划名已存在");
        }
        if (!StringUtils.isEmpty(reportPlanReq.getDeadLine())) {
            reportPlan.setReportEndTime(RegularUtil.calReportTime(Integer.valueOf(reportPlanReq.getFrequency())
                    , Integer.valueOf(reportPlanReq.getDeadLine())));
            reportPlan.setDeadLine(reportPlanReq.getDeadLine());
        }
        reportPlan.setDeliveryStatus(DeliveryStatus.DELIVERY.getCode());
        reportPlan.setDeliveryType(reportPlanReq.getDeliveryType());
        reportPlan.setFrequency(Integer.parseInt(reportPlanReq.getFrequency()));
        reportPlan.setBeginTime(reportPlanReq.getBeginTime());
        reportPlan.setEndTime(reportPlanReq.getEndTime());
        reportPlan.setBiasDay(reportPlanReq.getBiasDay());
        reportPlan.setEnable(EnableStatus.OK.getCode());
        reportPlan.setDelFlag(DelFlag.NORMAL.getCode());
        reportPlan.setCreateBy(SecurityUtils.getLoginUser().getUsername());
        reportPlanMapper.insertReportPlan(reportPlan);

        List<ReportPlanDetail> reportPlanDetails = new ArrayList<>();

        for (String reportId : reportPlanReq.getReportIds()) {
            for (String deptId : reportPlanReq.getDeptIds()) {
                ReportPlanDetail reportPlanDetail = new ReportPlanDetail();
                reportPlanDetail.setReportId(Long.valueOf(reportId));
                reportPlanDetail.setDeptId(Long.valueOf(deptId));
                reportPlanDetail.setPlanId(reportPlan.getPlanId());
                reportPlanDetails.add(reportPlanDetail);
            }
        }

        reportPlanDetailMapper.insertReportPlanDetailBatch(reportPlanDetails);
    }

    @Transactional(rollbackFor = Throwable.class)
    public void editReportPlan(EditReportPlanReq editReportPlanReq) throws Exception {
        ReportPlan reportPlan = new ReportPlan();
        reportPlan.setPlanId(Long.valueOf(editReportPlanReq.getPlanId()));
        reportPlan.setPlanName(editReportPlanReq.getPlanName());
        int num = reportPlanMapper.countUpdatePlanName(reportPlan);
        if (num > 0) {
            throw new Exception("计划名已存在");
        }


        if (!StringUtils.isEmpty(editReportPlanReq.getDeadLine())) {
            reportPlan.setReportEndTime(RegularUtil.calReportTime(Integer.valueOf(editReportPlanReq.getFrequency())
                    , Integer.valueOf(editReportPlanReq.getDeadLine())));
            reportPlan.setDeadLine(editReportPlanReq.getDeadLine());
        }

        reportPlan.setDeliveryType(editReportPlanReq.getDeliveryType());
        reportPlan.setFrequency(Integer.parseInt(editReportPlanReq.getFrequency()));
        reportPlan.setBeginTime(editReportPlanReq.getBeginTime());
        reportPlan.setEndTime(editReportPlanReq.getEndTime());
        reportPlan.setBiasDay(editReportPlanReq.getBiasDay());
        reportPlan.setUpdateBy(SecurityUtils.getLoginUser().getUsername());

        reportPlanMapper.updateReportPlanById(reportPlan);

        reportPlanDetailMapper.deleteByPlanId(Long.valueOf(editReportPlanReq.getPlanId()));
        List<ReportPlanDetail> reportPlanDetails = new ArrayList<>();

        for (String reportId : editReportPlanReq.getReportIds()) {
            for (String deptId : editReportPlanReq.getDeptIds()) {
                ReportPlanDetail reportPlanDetail = new ReportPlanDetail();
                reportPlanDetail.setReportId(Long.valueOf(reportId));
                reportPlanDetail.setDeptId(Long.valueOf(deptId));
                reportPlanDetail.setPlanId(reportPlan.getPlanId());
                reportPlanDetails.add(reportPlanDetail);
            }
        }

        reportPlanDetailMapper.insertReportPlanDetailBatch(reportPlanDetails);
    }

    public ReportPlanAllRep detail(Detail detail) throws Exception {
        ReportPlan reportPlan = reportPlanMapper.selectById(Long.valueOf(detail.getId()));
        if (DelFlag.DEL.getCode().equals(reportPlan.getDelFlag())) {
            throw new Exception("此计划已经被删除");
        }
        ReportPlanAllRep reportPlanAllRep = new ReportPlanAllRep();
        reportPlanAllRep.setEnable(reportPlan.getEnable());
        reportPlanAllRep.setCreateTime(reportPlan.getCreateTime());
        reportPlanAllRep.setUpdateBy(reportPlan.getUpdateBy());
        reportPlanAllRep.setCreateBy(reportPlan.getCreateBy());
        reportPlanAllRep.setBeginTime(reportPlan.getBeginTime());
        reportPlanAllRep.setBiasDay(reportPlan.getBiasDay());
        reportPlanAllRep.setDeliveryStatus(reportPlan.getDeliveryStatus());
        reportPlanAllRep.setDeliveryType(reportPlan.getDeliveryType());
        reportPlanAllRep.setPlanId(reportPlan.getPlanId());
        reportPlanAllRep.setPlanName(reportPlan.getPlanName());
        reportPlanAllRep.setDeadLine(reportPlan.getDeadLine());
        reportPlanAllRep.setEndTime(reportPlan.getEndTime());
        reportPlanAllRep.setFrequency(reportPlan.getFrequency());
        reportPlanAllRep.setReportEndTime(reportPlan.getReportEndTime());
        List<ReportPlanDetailName> reportPlanDetailNames = reportPlanDetailMapper.selectByPlanId(reportPlanAllRep.getPlanId());
        Set<IdName> deptSet = new HashSet<>();
        Set<IdName> reportSet = new HashSet<>();
        for (ReportPlanDetailName planDetail : reportPlanDetailNames) {
            IdName dept = new IdName();
            dept.setId(planDetail.getDeptId());
            dept.setName(planDetail.getDeptName());
            IdName report = new IdName();
            report.setId(planDetail.getReportId());
            report.setName(planDetail.getReportName());
            deptSet.add(dept);
            reportSet.add(report);
        }
        reportPlanAllRep.setReportIds(new ArrayList<>(reportSet));
        reportPlanAllRep.setDeptIds(new ArrayList<>(deptSet));


        return reportPlanAllRep;
    }

    public List<ReportPlanAllRep> list(ReportPlanListReq req) {
        List<ReportPlan> reportPlans = reportPlanMapper.selectFuzzy(req);
        List<ReportPlanAllRep> reportPlanAllReps = new ArrayList<>();
        for (ReportPlan reportPlan : reportPlans) {
            ReportPlanAllRep reportPlanAllRep = new ReportPlanAllRep();
            reportPlanAllRep.setEnable(reportPlan.getEnable());
            reportPlanAllRep.setCreateTime(reportPlan.getCreateTime());
            reportPlanAllRep.setUpdateBy(reportPlan.getUpdateBy());
            reportPlanAllRep.setCreateBy(reportPlan.getCreateBy());
            reportPlanAllRep.setBeginTime(reportPlan.getBeginTime());
            reportPlanAllRep.setBiasDay(reportPlan.getBiasDay());
            reportPlanAllRep.setDeliveryStatus(reportPlan.getDeliveryStatus());
            reportPlanAllRep.setDeliveryType(reportPlan.getDeliveryType());
            reportPlanAllRep.setPlanId(reportPlan.getPlanId());
            reportPlanAllRep.setPlanName(reportPlan.getPlanName());
            reportPlanAllRep.setDeadLine(reportPlan.getDeadLine());
            reportPlanAllRep.setFrequency(reportPlan.getFrequency());
            reportPlanAllRep.setReportEndTime(reportPlan.getReportEndTime());
            reportPlanAllRep.setEndTime(reportPlan.getEndTime());
            List<ReportPlanDetailName> reportPlanDetailNames = reportPlanDetailMapper.selectByPlanId(reportPlanAllRep.getPlanId());
            Set<IdName> deptSet = new HashSet<>();
            Set<IdName> reportSet = new HashSet<>();
            for (ReportPlanDetailName planDetail : reportPlanDetailNames) {
                IdName dept = new IdName();
                dept.setId(planDetail.getDeptId());
                dept.setName(planDetail.getDeptName());
                IdName report = new IdName();
                report.setId(planDetail.getReportId());
                report.setName(planDetail.getReportName());
                deptSet.add(dept);
                reportSet.add(report);
            }
            reportPlanAllRep.setReportIds(new ArrayList<>(reportSet));
            reportPlanAllRep.setDeptIds(new ArrayList<>(deptSet));
            reportPlanAllReps.add(reportPlanAllRep);
        }
        return reportPlanAllReps;
    }

    @Transactional(rollbackFor = Throwable.class)
    public void delete(Detail detail) throws Exception {
        List<ReportTask> reportTasks = reportTaskMapper.selectDeliveredTaskByPlanId(Long.valueOf(detail.getId()));
        if (reportTasks != null && !reportTasks.isEmpty()) {
            throw new Exception("计划中存在已经下发的任务实例");
        }
        ReportPlan reportPlan = new ReportPlan();
        reportPlan.setUpdateBy(SecurityUtils.getLoginUser().getUsername());
        reportPlan.setPlanId(Long.valueOf(detail.getId()));
        ReportTask reportTask = new ReportTask();
        reportTask.setUpdateBy(SecurityUtils.getLoginUser().getUsername());
        reportTask.setPlanId(Long.valueOf(detail.getId()));

        reportPlanMapper.deleteByPlanId(reportPlan);
        reportTaskMapper.deleteByPlanId(reportTask);
    }

    @Transactional(rollbackFor = Throwable.class)
    public void delivery(DeliveryReq detail) throws Exception {
        ReportPlan reportPlan = reportPlanMapper.selectById(Long.valueOf(detail.getId()));
        if (DelFlag.DEL.getCode().equals(reportPlan.getDelFlag())) {
            throw new Exception(reportPlan.getPlanName() + " 计划已经被删除");
        }

        if (EnableStatus.DISABLE.getCode().equals(reportPlan.getEnable())) {
            throw new Exception(reportPlan.getPlanName() + " 计划已经被禁用");
        }

        if (DeliveryStatus.DELIVERED.getCode().equals(reportPlan.getDeliveryStatus())) {
            throw new Exception(reportPlan.getPlanName() + " 计划已经下发过");
        }

        reportPlan.setUpdateBy(SecurityUtils.getLoginUser().getUsername());
        ReportTask reportTask = new ReportTask();
        reportTask.setPlanId(reportPlan.getPlanId());
        reportTask.setTaskStatus(TaskStatus.DELIVERED.getCode());
        reportTask.setTaskType(TaskType.HAND.getCode());
        reportTask.setCreateBy(SecurityUtils.getLoginUser().getUsername());
        reportTask.setDataDate(detail.getDataDate());

        reportPlanMapper.deliveryByID(reportPlan);
        reportTaskMapper.deliveryByPlanID(reportTask);
    }

    public void enable(Detail detail) throws Exception {
        ReportPlan reportPlan = reportPlanMapper.selectById(Long.valueOf(detail.getId()));
        if (DelFlag.DEL.getCode().equals(reportPlan.getDelFlag())) {
            throw new Exception("此计划已经被删除");
        }
        reportPlan.setUpdateBy(SecurityUtils.getLoginUser().getUsername());
        if (reportPlan.getEnable().equals(EnableStatus.OK.getCode())) {
            reportPlan.setEnable(EnableStatus.DISABLE.getCode());
        } else {
            reportPlan.setEnable(EnableStatus.OK.getCode());
        }
        reportPlanMapper.enable(reportPlan);
    }
}
